package robots;

import java.util.ArrayList;
import java.util.HashMap;

import maze.Barcode;
import maze.Coordinate;
import maze.Location;
import maze.Maze;
import pacman.Game;
import pacman.protocol.GhostProtocolProcessor;


/**
 * A class representing a simple version of a ghost. 
 * To be used !ONLY! for the other ghosts in a game.
 */
public class Ghost extends Robot {	
	/**
	 * True if this Ghosts thinks it has found pacman
	 */
	private boolean pacmanFound;
	
	/**
	 * A list of the mazes that match with this ghost's maze.
	 */
	protected Ghost[] matchedGhosts;	
	/**
	 * The name of this player/robot
	 */
	private String name;	
	/**
	 * True if this player thinks he captured pacman
	 */
	private boolean captured;	
	/**
	 * Indicates what version of the communication protocol this player uses.
	 */
	private String version;	
	/**
	 * The list of sectors this player's robot will drive to
	 */
	private ArrayList<Location> plan;	

	/**
	 * The game in which this ghost is riding around.
	 */
	private Game game;	
	/**
	 * The last coordinate where this ghost has seen pacman.
	 * This is recorded here because this position is the one in this ghost's own maze, not the real one.
	 */
	protected Coordinate coordinatePacman;	
	/**
	 * This ghost's own interpretation of the maze.
	 */
	private Maze maze;	
	/**
	 * A HashMap containing the mazes of the other ghosts.
	 */
	protected HashMap<String,Maze> mazesOtherRobots;
	/**
	 * True if this ghost's thread is done
	 */
	public boolean terminated = false;	
	/**
	 * True if this ghost has send it's name.
	 */
	public boolean hasSendName;	

	public GhostProtocolProcessor protocolProcessor;	
	public boolean readySetGo;
	
	/**
	 * Initializes a new simple ghost at own location 0,0
	 */
	public Ghost(Coordinate co, Game game, String name){
		super();
		setCoordinate(co);
		setName(name);
		setGame(game);
		matchedGhosts = new Ghost[0];
		mazesOtherRobots = new HashMap<String, Maze>();
		foundPacman(false);
		capturedPacman(false);
		setMaze(new Maze(10));
		setSendName(false);
		setPlan(new ArrayList<Location>());
		protocolProcessor = new GhostProtocolProcessor(this);
		readySetGo = false;
	}

	public void lastPreparations() {
		for(Ghost otherGhost: getGame().getOtherGhostsThan(getName())){
			addOtherRobotMaze(otherGhost);
		}
		readySetGo = true;
	}
	
	/**
	 * Adds the maze of a new ghost to the list of other ghost's mazes.
	 * Fails if there was already a ghost's maze with the given name.
	 */
	public void addOtherRobotMaze(Ghost otherGhost){
		Maze newMaze = new Maze(10);
		if(!mazesOtherRobots.containsKey(otherGhost.getName())){
			this.mazesOtherRobots.put(otherGhost.getName(), newMaze);
		}else{
			if(!getGame().ownGame){
				System.err.println("naam zat al in map");
			}
		}
	}
	
	public void printMazes(){
		System.out.println("Grootte van mazes voor ghost" + getName() + ": " + getMazesOtherRobots().size());
		System.out.println("Inhoud: ");
		for(String name: getMazesOtherRobots().keySet()){
			System.out.println(name + ": " + getMazesOtherRobots().get(name));
		}
	}
	
	public Maze getMazeOnName(String name){
		return mazesOtherRobots.get(name);
	}
	public HashMap<String, Maze> getMazesOtherRobots(){
		return mazesOtherRobots;
	}
	
	public boolean hasFoundPacman() {
		return pacmanFound;
	}
	public void foundPacman(boolean pacmanFound) {
		this.pacmanFound = pacmanFound;
	}

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

	public boolean hasCapturedPacman() {
		return captured;
	}
	public void capturedPacman(boolean captured) {
		this.captured = captured;
	}

	public ArrayList<Location> getPlan() {
		return plan;
	}
	public void setPlan(ArrayList<Location> plan) {
		this.plan = plan;
	}

	public Game getGame() {
		return game;
	}
	private void setGame(Game game) {
		this.game = game;
	}
	
	public void addMatchingGhost(Ghost ghost){
		if(!alreadyMatchedGhost(ghost) && ghost != null){
			int size = matchedGhosts.length;
			Ghost[] tempGhost = new Ghost[size];
			for(int i=0; i<matchedGhosts.length;i++){
				tempGhost[i] = matchedGhosts[i];
			}
			matchedGhosts = new Ghost[size+1];
			for(int i=0; i<tempGhost.length;i++){
				matchedGhosts[i] = tempGhost[i];
			}
			matchedGhosts[size] = ghost;
			System.out.println("addmatchingGhosts: "+this.getName()+"with "+ghost.getName());
		}
	}
	
	/**
	 * Checks if the given maze is already in the list of matching mazes.
	 * True if that is the case, False if not
	 */
	public boolean alreadyMatchedGhost(Ghost ghost){
		if(ghost == null)
			return false;
		if(this.getName().equals(ghost.getName())){
			return true;
		}
		else{
			for (int i = 0; i < this.matchedGhosts.length; i++) {
				if(this.matchedGhosts[i].getName().equals(ghost.getName()))
					return true;
			}
		}
		return false;
	}

	public String getVersion() {
		return version;
	}
	public void setVersion(String version) {
		this.version = version;
	}

	public boolean hasSendName() {
		return hasSendName;
	}
	public void setSendName(boolean send){
		this.hasSendName = send;
	}
	
	public Maze getMaze() {
		return maze;
	}
	private void setMaze(Maze maze) {
		this.maze = maze;
	}
	
	public Coordinate getCoordinatePacman() {
		return coordinatePacman;
	}
	public void setCoordinatePacman(Coordinate pacman){
		//System.out.println("pacmanlocationupdated: "+pacman.getX()+" "+pacman.getY());
		coordinatePacman=pacman;
		foundPacman(true);
	}
	public Ghost[] getMatchedGhost(){
		return this.matchedGhosts;
	}
}
